package PostfixCalc;
use strict;

use Calculator::Operator;
our $label = 0;

# Modify semantics: now translate to postfix
my $powers = sub { shift().' '.shift().' **' };

Operator->make_sem(
   expr => {
      '+' => sub { shift().' '.shift().' +'  },
      '-' => sub { shift().' '.shift().' -' },
    },
    term => {
      '*' => sub { shift().' '.shift().' *'  },
      '/' => sub { shift().' '.shift().' /' },
    },
    power => {
      '^'  => $powers,
      '**' => $powers,
    },
    uneg => { 
       # use ~ for unary minus
      'NEG' => sub { shift().' ~' }, 
    },
    factorial => { 
      '!' => sub { shift().' !'},     
    },
    statements => {
      ';' => sub { shift().' ; '.shift() },
    },
    exprequal => {
      '==' => sub { shift().' '.shift().' =='  },
      '!=' => sub { shift().' '.shift().' !=' },
    },
    exprrel => {
      '<' => sub { shift().' '.shift().' <'  },
      '>' => sub { shift().' '.shift().' >' },
      '<=' => sub { shift().' '.shift().' <=' },
      '>=' => sub { shift().' '.shift().' >=' },
    },
);

no warnings 'redefine';

package lvalue;
sub ceval {
  my $self = shift;
  
  return $self->{var};
}


package rvalue;
sub ceval {
  my $self = shift;

  return $self->{var};
}

package factor;
sub ceval {
  my $self = shift;

  return $self->{val};
}

package assignation;

sub ceval{
   my $self = shift;
   return ($self->{right}->ceval()) .' '. ($self->{left}->ceval()).' =';
}

package ifstatement;

sub ceval{
   my $self = shift;
   my $l = ++$label; #localiza la label
   my $trad = $self->{expr}->ceval()." jz else$l ".$self->{true}->ceval();
   if (defined $self->{false}){
      my $l2 = ++$label;
      $trad .= " j endif$l2 :else$l ".$self->{false}->ceval()." :endif$l2 ";
   }
   else{
      $trad .= " :else$l ";
   }
   return $trad;
}

1;
